// VideoController.v
//
// Description:
// ------------
//
//
// 
// Copyright Jabeer Ahmed and Caleb Mathisen, 2014
// 
// Created By:      Caleb Mathisen
// Author(s) :      Jabeer Ahmed, Caleb Mathisen
// Last Modified:   1/19/2014
//
// Revision History:
// -----------------
///////////////////////////////////////////////////////////////////////////

module VideoController_IF (

    /*********** BotSim ***********/
    input   [1:0]   world_pixel_in,     // World pixel value from BotSim
    input   [7:0]   BotInfo_in,         // BotInfo to indicate bot heading
    input   [7:0]   Loc_x_in,           // bot loc x (assume origin bottom-left)
    input   [7:0]   Loc_y_in,           // bot loc y (assume origin bottom-left)

    input           clk100,             // 100MHz system clock
    input           reset,              // System reset

    input           icon_toggle,

    output  [9:0]   pxl_row,            // screen pixel row out to botSim
    output  [9:0]   pxl_col,            // screen pixel column out to botSim

    /********** External **********/
    output          vert_sync,          // VGA V_Sync: out to monitor (external)
    output          horz_sync,          // VGA H_Sync: out to monitor (external)
    output  [2:0]   red,                // VGA red   : out to monitor (external)
    output  [2:0]   green,              // VGA green : out to monitor (external)
    output  [1:0]   blue                // VGA blue  : out to monitor (external)

);

/*******************************************************************************
                            Internal Variables
 ******************************************************************************/
    
    wire            clk25;                          // 25 MHz clock for display

    /*** Display Timing Gen ***/
    wire            dtg_hsync_out;
    wire            dtg_vsync_out;
    wire            dtg_video_on_clr;
    wire    [9:0]   dtg_pxl_row_icn;
    wire    [9:0]   dtg_pxl_col_icn;    

    /****** Icon Module *******/
    wire    [1:0]   icn_icon_clr;

    /******** Output **********/
    wire    [2:0]   red_out;             
    wire    [2:0]   green_out;          
    wire    [1:0]   blue_out;            
    wire    [9:0]   pxl_row_out;        // screen pixel row to outport
    wire    [9:0]   pxl_col_out;        // screen pixel column to outport

    assign red      = red_out;          // connect to outport
    assign green    = green_out;        // connect to outport
    assign blue     = blue_out;         // connect to outport   
    assign pxl_row  = pxl_row_out;      // connect to outport
    assign pxl_col  = pxl_col_out;      // connect to outport

/*******************************************************************************
                          Submodule Instantiation
 ******************************************************************************/

    /************************ Display Timing Gen. ************************/

    assign horz_sync = dtg_hsync_out;       // connect dtg hsync out to outport
    assign vert_sync = dtg_vsync_out;       // connect dtg vsync out to outport

    dtg disp_t_gen (
        /********* Inputs *********/
        .clock       (clk25),               // 25MHz clk from dtg
        .rst         (reset),               // system reset
        /********* Output *********/
        .horiz_sync  (dtg_hsync_out),       // connect dtg hsync out to outport 
        .vert_sync   (dtg_vsync_out),       // connect dtg vsync out to outport
        .video_on    (dtg_video_on_clr),    // connect dtg video_on to colorizer
        .pixel_row   (pxl_row_out),         // connect pixel_row to outport wire
        .pixel_column(pxl_col_out)          // connect pixel_col to outport wire
    );

    /**************************** Icon Module ****************************/

    wire    [1:0]   boticn_icon_mplex;

    assign dtg_pxl_row_icn = pxl_row_out[9:0];   // connect to dtg pxl out port
    assign dtg_pxl_col_icn = pxl_col_out[9:0];   // connect to dtg pxl out port

    Icon bot_icon (
		.clk(clk25),
        /**** Disp Timing Gen *****/
        .pixel_column   (dtg_pxl_col_icn),  // connect to pxl row input
        .pixel_row      (dtg_pxl_row_icn),  // connect to pxl col input
        /********* BotSIM *********/        
        .Loc_X          ({Loc_x_in,2'b0}),          
        .Loc_Y          ({Loc_y_in,2'b0}),          
        .BotInfo        (BotInfo_in),            
        /********* Output *********/
        .icon           (boticn_icon_mplex)
    );

    wire    [1:0]   doticn_icon_mplex;
    Icon_Dot icon_dot (
        .clk(clk25),
        /**** Disp Timing Gen *****/
        .pixel_column   (dtg_pxl_col_icn[9:2]),  // connect to pxl row input
        .pixel_row      (dtg_pxl_row_icn[9:2]),  // connect to pxl col input
        /********* BotSIM *********/        
        .Loc_X          (Loc_x_in),          
        .Loc_Y          (Loc_y_in),          
        /********* Output *********/
        .icon           (doticn_icon_mplex)
    );


    /***************************** Colorizer *****************************/
    reg     [1:0]       icn_mplexr;
    assign icn_icon_clr = icn_mplexr;

    always @(*) begin
        if (icon_toggle == 1'b1) begin
            icn_mplexr <= boticn_icon_mplex;
        end
		  else begin
            icn_mplexr <= doticn_icon_mplex;            
        end
    end

    Colorizer colorizer (
		.clk 			(clk25),
        .video_on       (dtg_video_on_clr),
        .world_pixel    (world_pixel_in),
        .icon           (icn_icon_clr),
        .red            (red_out),
        .green          (green_out),
        .blue           (blue_out) 
    );

    /************************** Icon Block ROM ***************************/
    wire clk100_in;
    assign clk100_in = clk100;
     
    wire            clkfb_in, clk0_buf;
    // DCM clock feedback buffer
    BUFG CLK0_BUFG_INST (.I(clk0_buf), .O(clkfb_in));

    DCM_SP #(
        .CLKDV_DIVIDE(4.0), // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
        // 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
        .CLKFX_DIVIDE(1), // Can be any integer from 1 to 32
        .CLKFX_MULTIPLY(4), // Can be any integer from 2 to 32
        .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
        .CLKIN_PERIOD(10.0), // Specify period of input clock
        .CLKOUT_PHASE_SHIFT("NONE"), // Specify phase shift of NONE, FIXED or VARIABLE
        .CLK_FEEDBACK("1X"), // Specify clock feedback of NONE, 1X or 2X
        .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
        // an integer from 0 to 15
        .DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL
        .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
        .PHASE_SHIFT(0), // Amount of fixed phase shift from -255 to 255
        .STARTUP_WAIT("FALSE")) // Delay configuration DONE until DCM LOCK, TRUE/FALSE
    DCM_SP_inst (
        .CLK0(clk0_buf), // 0 degree DCM CLK output
        .CLK180(), // 180 degree DCM CLK output
        .CLK270(), // 270 degree DCM CLK output
        .CLK2X(), // 2X DCM CLK output
        .CLK2X180(), // 2X, 180 degree DCM CLK out
        .CLK90(), // 90 degree DCM CLK output
        .CLKDV(clk25), // Divided DCM CLK out (CLKDV_DIVIDE)
        .CLKFX(), // DCM CLK synthesis out (M/D)
        .CLKFX180(), // 180 degree CLK synthesis out
        .LOCKED(), // DCM LOCK status output
        .PSDONE(), // Dynamic phase adjust done output
        .STATUS(), // 8-bit DCM status bits output
        .CLKFB(clkfb_in), // DCM clock feedback
        .CLKIN(clk100_in), // Clock input (from IBUFG, BUFG or DCM)
        .PSCLK(1'b0), // Dynamic phase adjust clock input
        .PSEN(1'b0), // Dynamic phase adjust enable input
        .PSINCDEC(1'b0), // Dynamic phase adjust increment/decrement
        .RST(1'b0) // DCM asynchronous reset input
    );

endmodule